package com.lyy.common.shiro;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.lyy.common.utils.Constants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

@Slf4j
public class JWTUtil {

    /**
     * 返回结果
     *
     * @param status
     * @param json
     * @return
     */
    public static void writeResponse(HttpServletResponse response, int status, Object json) {
        try {
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "*");
            response.setContentType("application/json;charset=UTF-8");
            response.setStatus(status);
            response.getWriter().write(JSONObject.toJSONString(json));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据参数或者header获取accessToken
     *
     * @param request
     */
    public static String getToken(ServletRequest request) {
        HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
        String loginToken = httpServletRequest.getParameter(Constants.LOGIN_TOKEN);
        if (StringUtils.isBlank(loginToken)) {
            loginToken = httpServletRequest.getHeader(Constants.LOGIN_TOKEN);
        }
        return loginToken;
    }

    /**
     * 生成token
     *
     * @param username
     * @return
     */
    public static String sign(String username, String secret) {
        Algorithm algorithm = Algorithm.HMAC256(secret);
        // 指定过期时间
        Date date = new Date(System.currentTimeMillis() + Constants.EXPIRE_TIME);
        return JWT.create()
                .withClaim("username", username)
                .withExpiresAt(date)
                .sign(algorithm);
    }

    /**
     * 生成token
     *
     * @param username
     * @return
     */
    public static String signLong(String username, String secret) {
        Algorithm algorithm = Algorithm.HMAC256(secret);
        // 指定过期时间
        Date date = new Date(System.currentTimeMillis() + Constants.EXPIRE_LONG_TIME);
        return JWT.create()
                .withClaim("username", username)
                .withExpiresAt(date)
                .sign(algorithm);
    }

    /**
     * 校验token是否正确
     *
     * @param token    密钥
     * @param username 登录名
     * @return
     */
    public static boolean verify(String token, String username, String secret) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withClaim("username", username)
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            log.debug("校验token:" + JSON.toJSONString(jwt));
            return true;
        } catch (IllegalArgumentException | JWTVerificationException e) {
            return false;
        }
    }

    /**
     * 获取登录名
     *
     * @param token
     * @return
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }


    /**
     * 生成token
     * @param username
     * @return
     */
    public static String sign(String username) {
        String secret = username + Constants.SALT;
        Algorithm algorithm = Algorithm.HMAC256(secret);
        // 指定过期时间
        Date date = new Date(System.currentTimeMillis() + Constants.EXPIRE_TIME);
        return JWT.create()
                .withClaim("username", username)
                .withExpiresAt(date)
                .sign(algorithm);
    }

}